package com.zx.video28181.activity;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.pm.PackageManager;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaCodec;
import android.media.MediaFormat;
import android.media.MediaRecorder;
import android.util.Log;

import androidx.core.app.ActivityCompat;

import com.zx.video28181.sip.ClientListener;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;

public class AudioRecordIm implements ClientListener.GetAudioRecord {

    private static final String TAG = "AudioRecordIm";

    private AudioRecord audioRecord;

    private MediaCodec mAudioEncoder;

    ByteBuffer[] encodeInputBuffers;

    ByteBuffer[] encodeOutputBuffers;

    MediaCodec.BufferInfo mAudioEncodeBufferInfo;

    byte[] mbuffer;

    private BlockingDeque<byte[]> queue = new LinkedBlockingDeque<>();

    public AudioRecordIm() {
        initAudioRecord();
    }


    /**
     *  录音初始化
     */
    @SuppressLint("MissingPermission")
    private void initAudioRecord() {
        int audioSource = MediaRecorder.AudioSource.MIC;
        int sampleRate = 44100;
        int channelConfig = AudioFormat.CHANNEL_IN_MONO;
        int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
        int minBufferSize = android.media.AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
        mbuffer = new byte[minBufferSize];
        audioRecord = new AudioRecord(audioSource, sampleRate, channelConfig, audioFormat, Math.max(minBufferSize, 2048));
    }
    private void initAudioEncoder() {
        try {
            mAudioEncoder = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_AUDIO_AAC);
            MediaFormat format = MediaFormat.createAudioFormat(MediaFormat.MIMETYPE_AUDIO_AAC, 44100, 1);
            format.setInteger(MediaFormat.KEY_BIT_RATE, 96000);//比特率
            format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 1024 * 1024);
            mAudioEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (mAudioEncoder == null) {
            Log.e(TAG, "create mediaEncode failed");
            return;
        }

        mAudioEncoder.start(); // 启动MediaCodec,等待传入数据
        encodeInputBuffers = mAudioEncoder.getInputBuffers(); //上面介绍的输入和输出Buffer队列
        encodeOutputBuffers = mAudioEncoder.getOutputBuffers();
        mAudioEncodeBufferInfo = new MediaCodec.BufferInfo();
    }


    @Override
    public void init() {
        initAudioRecord();
        initAudioEncoder();
    }

    @Override
    public byte[] startRecord() {
        audioRecord.startRecording();
        int read = audioRecord.read(mbuffer, 0, 2048);
        if (read > 0) {
            byte[] audio = new byte[read];
            System.arraycopy(mbuffer, 0, audio, 0, read);
            encodeData(audio);
            return  audio;
        }
        return null;
    }

    @Override
    public byte[] getdata() {
        return getPCMData();
    }

    /**
     * 将PCM数据存入队列
     */
    private void putPCMData(byte[] pcmChunk) {
        Log.e(TAG, "putPCMData");
        try {
            queue.put(pcmChunk);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 从队列取出PCM数据
     */
    private byte[] getPCMData() {
        try {
            if (queue.isEmpty()) {
                return null;
            }
            return queue.take();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }
    public void encodeData(byte[] data) {
        //dequeueInputBuffer（time）需要传入一个时间值，-1表示一直等待，0表示不等待有可能会丢帧，其他表示等待多少毫秒
        //获取输入缓存的index
        int inputIndex = mAudioEncoder.dequeueInputBuffer(-1);
        if (inputIndex >= 0) {
            ByteBuffer inputByteBuf = encodeInputBuffers[inputIndex];
            inputByteBuf.clear();
            //添加数据
            inputByteBuf.put(data);
            //限制ByteBuffer的访问长度
            inputByteBuf.limit(data.length);
            //把输入缓存塞回去给MediaCodec
            mAudioEncoder.queueInputBuffer(inputIndex, 0, data.length, 0, 0);
        }
        //获取输出缓存的index
        int outputIndex = mAudioEncoder.dequeueOutputBuffer(mAudioEncodeBufferInfo, 0);
        while (outputIndex >= 0) {
            //获取缓存信息的长度
            int byteBufSize = mAudioEncodeBufferInfo.size;

            //拿到输出Buffer
            ByteBuffer outPutBuf = encodeOutputBuffers[outputIndex];
            outPutBuf.position(mAudioEncodeBufferInfo.offset);
            outPutBuf.limit(mAudioEncodeBufferInfo.offset + mAudioEncodeBufferInfo.size);

            byte[] aacData = new byte[byteBufSize];
            /*
            get（byte[] dst,int offset,int length）:ByteBuffer从position位置开始读，读取length个byte，并写入dst下
            标从offset到offset + length的区域
             */
            outPutBuf.get(aacData, 0, byteBufSize);
            outPutBuf.position(mAudioEncodeBufferInfo.offset);

            putPCMData(aacData); // PCM数据放入队列，等待编码
            //释放
            mAudioEncoder.releaseOutputBuffer(outputIndex, false);
            outputIndex = mAudioEncoder.dequeueOutputBuffer(mAudioEncodeBufferInfo, 0);
        }
    }


}
